﻿using Koala.Pro.Core;
using Koala.Pro.Core.Dto;
using Koala.Pro.Core.Models;
using Koala.Pro.Helpers;
using System.Collections.ObjectModel;

namespace Koala.Pro.Common.Extension
{
    public static class TreeNodeExtension
    {
        public static List<T> FindNodes<T>(this IEnumerable<T> nodes, string name) where T : DictTypeNodeDto
        {
            List<T> list = new List<T>();
            foreach (T node in nodes)
            {
                if (node.Name.Contains(name))
                {
                    list.Add(node);
                }
                foreach (DictTypeNodeDto item in node.Children.FindNodes(name))
                {
                    list.Add((T)item);
                }
            }
            return list;
        }

        public static T Find<T>(this IEnumerable<T> nodes, string name) where T : DictTypeNodeDto
        {
            foreach (T node in nodes)
            {
                if (node.Name.Contains(name))
                {
                    return node;
                }
                if (node.Children.Count > 0)
                {
                    DictTypeNodeDto dictTypeNodeDto = node.Children.Find(name);
                    if (dictTypeNodeDto != null)
                    {
                        return (T)dictTypeNodeDto;
                    }
                }
            }
            return null;
        }

        public static List<T> FindCustomNodes<T>(this IEnumerable<T> nodes, Predicate<T> predicate) where T : CustomTreeNode
        {
            List<T> list = new List<T>();
            foreach (T node in nodes)
            {
                if (predicate(node))
                {
                    list.Add(node);
                }
                foreach (T item in ((IEnumerable<T>)node.Children).FindCustomNodes(predicate))
                {
                    list.Add(item);
                }
            }
            return list;
        }

        public static List<T> FindRoleNodes<T>(this IEnumerable<T> nodes, Predicate<T> predicate) where T : RoleAndDeptTreeNode
        {
            List<T> list = new List<T>();
            foreach (T node in nodes)
            {
                if (predicate(node))
                {
                    list.Add(node);
                }
                foreach (T item in ((IEnumerable<T>)node.Children).FindRoleNodes(predicate))
                {
                    list.Add(item);
                }
            }
            return list;
        }

        public static List<T> FindOuNodes<T>(this IEnumerable<T> nodes, Predicate<T> predicate) where T : OuInfo
        {
            List<T> list = new List<T>();
            foreach (T node in nodes)
            {
                if (predicate(node))
                {
                    list.Add(node);
                }
                foreach (T item in ((IEnumerable<T>)node.Children).FindOuNodes(predicate))
                {
                    list.Add(item);
                }
            }
            return list;
        }

        public static List<T> FindFunctionNodes<T>(this IEnumerable<T> nodes, Predicate<T> predicate) where T : FunctionInfo
        {
            List<T> list = new List<T>();
            foreach (T node in nodes)
            {
                if (predicate(node))
                {
                    list.Add(node);
                }
                foreach (T item in ((IEnumerable<T>)node.Children).FindFunctionNodes(predicate))
                {
                    list.Add(item);
                }
            }
            return list;
        }

        public static List<T> FindMenuNodes<T>(this IEnumerable<T> nodes, Predicate<T> predicate) where T : MenuInfo
        {
            List<T> list = new List<T>();
            foreach (T node in nodes)
            {
                if (predicate(node))
                {
                    list.Add(node);
                }
                foreach (T item in ((IEnumerable<T>)node.Children).FindMenuNodes(predicate))
                {
                    list.Add(item);
                }
            }
            return list;
        }

        public static void AddRange<T>(this ObservableCollection<T> collection, IEnumerable<T> items)
        {
            foreach (T item in items)
            {
                collection.Add(item);
            }
        }
    }
}
